package com.myk.game.gobangchess.rooms.oldrooms;

import com.myk.game.gobangchess.Sign;
import com.myk.game.gobangchess.signs.*;
import com.myk.game.gobangchess.constants.BoardStyleData;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.rooms.absrooms.AbsOneTwoTwoTwoStepRoom;
import com.sun.org.apache.xpath.internal.functions.FuncFalse;

import java.util.*;

/**
 * 防线房间
 */
public class FortificationRoom extends AbsOneTwoTwoTwoStepRoom {

    public FortificationRoom(String roomName) {
        super(roomName, "\t\t某猪设计的连接类新棋，第三届设计比赛作品。", "防线",BoardStyleData.getGoBangStyle(14,14), true, true);
    }

    @Override
    public String getRuleText() {
        return "黑棋先落一枚棋子，随后白黑双方轮流落下两枚棋子。\n" +
                "                如果一方落子后，把棋盘空位用对方棋子填满，对方也不满足胜利条件，则不可如此落子。\n" +
                "                \n" +
                "                胜利条件为，落子后，若存在3条由相邻的己方棋子组成的路径，满足：\n" +
                "                [A]将3枚自己的方形棋子两两相连；\n" +
                "                [B]无共用棋子；\n" +
                "                [C]包围中棋盘中心的四个方形棋子。\n" +
                "                其中\"相连\"包括横、斜相邻，但棋盘中6处绿色\"四宫格\"的对角线不视为相邻。\n" +
                "                \n" +
                "                一方无合法行动时，双方均失败。";
    }

    public  List<coordPair> unconnected=Arrays.asList(
            new coordPair(new coord(2, 5), new coord(3, 6)), new coordPair(new coord(3, 6), new coord(2, 5)),
            new coordPair(new coord(2, 6), new coord(3, 5)), new coordPair(new coord(3, 5), new coord(2, 6)),
            new coordPair(new coord(5, 2), new coord(6, 3)), new coordPair(new coord(6, 3), new coord(5, 2)),
            new coordPair(new coord(5, 3), new coord(6, 2)), new coordPair(new coord(6, 2), new coord(5, 3)),
            new coordPair(new coord(3, 9), new coord(4, 10)), new coordPair(new coord(4, 10), new coord(3, 9)),
            new coordPair(new coord(3, 10), new coord(4, 9)), new coordPair(new coord(4, 9), new coord(3, 10)),
            new coordPair(new coord(9, 3), new coord(10, 4)), new coordPair(new coord(10, 4), new coord(9, 3)),
            new coordPair(new coord(9, 4), new coord(10, 3)), new coordPair(new coord(10, 3), new coord(9, 4)),
            new coordPair(new coord(7, 10), new coord(8, 11)), new coordPair(new coord(8, 11), new coord(7, 10)),
            new coordPair(new coord(7, 11), new coord(8, 10)), new coordPair(new coord(8, 10), new coord(7, 11)),
            new coordPair(new coord(10, 7), new coord(11, 8)), new coordPair(new coord(11, 8), new coord(10, 7)),
            new coordPair(new coord(11, 7), new coord(10, 8)), new coordPair(new coord(10, 8), new coord(11, 7))
    ); //六处地形的对角线不连接
    public List<Sign> swamp=Arrays.asList(
            new GroundSign(getIndex(2,5),getIndex(3,6),"#FFAFEDC0","#FFAFEDC0",1f,0,0),
            new GroundSign(getIndex(5,2),getIndex(6,3),"#FFAFEDC0","#FFAFEDC0",1f,0,0),
            new GroundSign(getIndex(3,9),getIndex(4,10),"#FFAFEDC0","#FFAFEDC0",1f,0,0),
            new GroundSign(getIndex(9,3),getIndex(10,4),"#FFAFEDC0","#FFAFEDC0",1f,0,0),
            new GroundSign(getIndex(7,10),getIndex(8,11),"#FFAFEDC0","#FFAFEDC0",1f,0,0),
            new GroundSign(getIndex(10,7),getIndex(11,8),"#FFAFEDC0","#FFAFEDC0",1f,0,0)
    ); //把地形画在棋盘上
    public List<coord> availableMoves=new ArrayList<>();
    public static int[] dirX={-1,0,0,1,-1,-1,1,1}, dirY={0,1,-1,0,1,-1,1,-1};

    @Override
    protected void onStartPrepare() {
        curGrids=new int[][]{
                {0, 0, 0, 0, 0, 0, 0, 0,11, 0, 0, 0, 0, 0},
                {0,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,12},
                {0, 0, 0, 0, 0, 0,15,15, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0,15,15, 0, 0, 0, 0, 0, 0},
                {11,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,11, 0},
                {0, 0, 0, 0, 0,12, 0, 0, 0, 0, 0, 0, 0, 0}
        }; //11、12是黑白方块，15是黄色方块
        availableMoves.clear();
        firstPoint=null; secondPoint=null;
        noticeBlackMove();
    }

    @Override
    public String getGameInfo() {
        availableMoves=findAllAvailableMoves((this.cur==1)?1:2);
        signList.clear();
        signList.addAll(swamp);
        int indexTmp;
        for (coord availableMove : availableMoves) {
            indexTmp = getIndex(availableMove.row, availableMove.col);
            signList.add(new GroundSign(indexTmp, indexTmp, "#FF9F80F7", "#00000000", 1f, 0, 1));
        } //提示合法行动
        signList.addAll(tempPointSigns);
        return super.getGameInfo();
    }

    @Override
    public void doRule(int row, int col, int value) {
        if(curGrids[row][col]!=0) return;

        if(availableMoves.isEmpty()){
            doOver(WinMode.BOTH_DRAW,player_black.getNickNameOrTemp()+"与"+player_white.getNickNameOrTemp()+"都输了");
            return ;
        } //没有合法行动判双负（winmode没这个类型，只好用是和棋）

        if(!availableMoves.contains(new coord(row, col))) return;

        curGrids[row][col] = value;
        if(step == 0){
            stepAdd();
            firstPoint = new int[]{row,col,value};
            updateTempPointSigns();
            noticeChangeMove();
            return ;
        }

        if (firstPoint == null){ //修改自1222房间的double
            if(!availableMoves.contains(new coord(row, col))) return;
            firstPoint = new int[]{row,col,value};
            updateTempPointSigns();
            if(checkWin(value)){
                if(value==1)
                    doOver(WinMode.BLACK_WIN,player_black.getNickNameOrTemp()+"执黑棋战胜"+player_white.getNickNameOrTemp());
                else
                    doOver(WinMode.WHITE_WIN,player_white.getNickNameOrTemp()+"执白棋战胜"+player_black.getNickNameOrTemp());
                return;
            }
            noticeAllRefreshGameInfo();
        }else{
            if(!availableMoves.contains(new coord(row, col))) return;
            secondPoint = new int[]{row,col,value};
            updateTempPointSigns();
            stepAdd();
            if(checkWin(value)){
                if(value==1)
                    doOver(WinMode.BLACK_WIN,player_black.getNickNameOrTemp()+"执黑棋战胜"+player_white.getNickNameOrTemp());
                else
                    doOver(WinMode.WHITE_WIN,player_white.getNickNameOrTemp()+"执白棋战胜"+player_black.getNickNameOrTemp());
                return;
            }
            noticeChangeMove();
        }

    }

    public static class coord{
        public int row, col;
        public coord(int x,int y){
            this.row=x;
            this.col=y;
        }
        @Override
        public boolean equals(Object a) {
            if(this==a) return true;
            if(a==null|| getClass()!=a.getClass()) return false;
            coord aa=(coord) a;
            return row==aa.row && col==aa.col;
        }
        @Override
        public int hashCode() {
            return Objects.hash(row, col);
        }
    }
    public static class coordPair{
        public coord start, end;
        public coordPair(coord x,coord y){
            this.start=x;
            this.end=y;
        }
        @Override
        public boolean equals(Object a) {
            if(this==a) return true;
            if(a==null|| getClass()!=a.getClass()) return false;
            coordPair aa=(coordPair) a;
            return start==aa.start && end==aa.end;
        }
        @Override
        public int hashCode() {
            return Objects.hash(start, end);
        }
    }

    public List<coord> findAllAvailableMoves(int side){
        List<coord> availableMoves=new ArrayList<coord>();
        List<coord> path=new ArrayList<coord>();
        List<coord> stones=new ArrayList<coord>();
        long[] cntPath=new long[197]; //最后一个成员储存的是path的总数量

        for(int i=0;i<14;i++)
            for(int j=0;j<14;j++){
                cntPath[i*14+j]=0;
                if(curGrids[i][j]==0 || curGrids[i][j]==3-side || curGrids[i][j]==13-side)
                    stones.add(new coord(i,j));
                //与规则文本一致，此处假装把所有空格都落上对方棋子
            }
        cntPath[196]=0;

        if(side==2) cntPath=dfsc(1,0,8,path,stones,cntPath);
        else        cntPath=dfsc(2,1,1,path,stones,cntPath);

        System.out.println(cntPath[196]);

        for(int i=0;i<14;i++)
            for(int j=0;j<14;j++)
                if(cntPath[i*14+j]<cntPath[196] && curGrids[i][j]==0)
                    availableMoves.add(new coord(i,j));
                //某个点不能落子 iff (空格填上对方棋子后)所有获胜路线都要经过这个点
        return availableMoves;
    }

    @Override
    protected WinState checkWin(int row, int col) {
        //没这个东西它要报错哦，这可咋办呢呼呼呼
        return null;
    }

    protected boolean checkWin(int side) {
        List<coord> path=new ArrayList<coord>();
        List<coord> stones=new ArrayList<coord>();
        for(int i=0;i<14;i++)
            for(int j=0;j<14;j++)
                if(curGrids[i][j]==side || curGrids[i][j]==side+10)
                    stones.add(new coord(i,j));

        if(side==1) return dfsb(side,0,8,path,stones);
        else        return dfsb(side,1,1,path,stones);
    }

    protected boolean dfsb(int side,int row,int col,List<coord> path,List<coord> stones){
        //这个dfs返回是否获胜，检测到获胜即会结束，用于胜负判断

        return false;
    }

    protected long[] dfsc(int side,int row,int col,List<coord> path,List<coord> stones,long[] cntPath){
        //这个dfs枚举所有获胜路线中，返回某一枚棋子的途径次数，用于寻找可以落子的点位

        return null;
    }

    protected boolean checkConnect(int side, List<coord> path){
        //检测路径是否经过了三个己方控制的城镇
        //如果使用暴力方法，无需判断路径无共用棋子，其他方法可能还要判断
        if(side==1)
            return path.contains(new coord(0,8))&&path.contains(new coord(8,0))&&path.contains(new coord(12,12));
        else
            return path.contains(new coord(5,13))&&path.contains(new coord(13,5))&&path.contains(new coord(1,1));
    }

    protected boolean checkRing(List<coord> path){
        //从中心出发bfs，不能越过获胜路径，如果能够达到棋盘边界就说明没把中心围起来
        Queue<coord> Q=new LinkedList<>();
        coord curC,newC;
        int curRow,curCol,newRow,newCol;
        boolean[][] visited=new boolean[14][14];
        boolean flag=false;
        for(int i=0;i<14;i++)
            for(int j=0;j<14;j++)
                visited[i][j]=false;

        Q.add(new coord(6,6));
        visited[6][6]=true;
        while(!Q.isEmpty()){
            curC=Q.remove();
            curRow=curC.row; curCol=curC.col;
            for(int i=1;i<4;i++){  //由于斜线也算相连，此处是直向四邻（而非八邻），也即const数组里的前4项
                newRow=curRow+dirX[i]; newCol=curCol+dirY[i];
                newC=new coord(newRow,newCol);
                if(newRow<0 || newRow>13 || newCol<0 || newCol>13) continue;
                if(visited[newRow][newCol]) continue;
                if(path.contains(curC) && !path.contains(newC)) continue; //不能越过获胜路径
                visited[newRow][newCol]=true;
                Q.add(newC);
            }
        }

        for(int i=0;i<13;i++){
            if(visited[0][i] && !path.contains(new coord(0,i))) return false;
            if(visited[13][i] && !path.contains(new coord(0,i))) return false;
            if(visited[i][0] && !path.contains(new coord(0,i))) return false;
            if(visited[i][13] && !path.contains(new coord(0,i))) return false;
        }
        return true;
    }

}
